home *** CD-ROM | disk | FTP | other *** search
- /* See license.txt for terms of usage */
-
- FBL.ns(function() { with (FBL) {
-
- // ************************************************************************************************
- // Constants
-
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const jsdIScript = Ci.jsdIScript;
- const jsdIStackFrame = Ci.jsdIStackFrame;
- const jsdIExecutionHook = Ci.jsdIExecutionHook;
- const nsISupports = Ci.nsISupports;
- const nsICryptoHash = Ci.nsICryptoHash;
- const nsIURI = Ci.nsIURI;
-
- const PCMAP_SOURCETEXT = jsdIScript.PCMAP_SOURCETEXT;
-
- const RETURN_VALUE = jsdIExecutionHook.RETURN_RET_WITH_VAL;
- const RETURN_THROW_WITH_VAL = jsdIExecutionHook.RETURN_THROW_WITH_VAL;
- const RETURN_CONTINUE = jsdIExecutionHook.RETURN_CONTINUE;
- const RETURN_CONTINUE_THROW = jsdIExecutionHook.RETURN_CONTINUE_THROW;
- const RETURN_ABORT = jsdIExecutionHook.RETURN_ABORT;
-
- const TYPE_THROW = jsdIExecutionHook.TYPE_THROW;
-
- const STEP_OVER = 1;
- const STEP_INTO = 2;
- const STEP_OUT = 3;
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- const tooltipTimeout = 300;
-
- const reLineNumber = /^[^\\]?#(\d*)$/;
-
- const reEval = /\s*eval\s*\(([^)]*)\)/m; // eval ( $1 )
- const reHTM = /\.[hH][tT][mM]/;
- const reFunction = /\s*Function\s*\(([^)]*)\)/m;
-
- const panelStatus = $("fbPanelStatus");
-
- // ************************************************************************************************
-
- var listeners = [];
-
- // ************************************************************************************************
-
- Firebug.Debugger = extend(Firebug.ActivableModule,
- {
- fbs: fbs, // access to firebug-service in chromebug under browser.xul.DOM.Firebug.Debugger.fbs /*@explore*/
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Debugging
-
- evaluate: function(js, context, scope)
- {
- var frame = context.currentFrame;
- if (!frame)
- return;
-
- frame.scope.refresh(); // XXX what's this do?
-
- var result = {};
- var scriptToEval = js;
- if (scope && scope.thisValue) {
- // XXX need to stick scope.thisValue somewhere... frame.scope.globalObject?
- scriptToEval = " (function() { return " + js + " }).apply(__thisValue__);";
- }
-
- // This seem to be safe; eval'ing a getter property in content that tries to
- // be evil and get Components.classes results in a permission denied error.
- var ok = frame.eval(scriptToEval, "", 1, result);
-
- var value = result.value.getWrappedValue();
- if (ok)
- return value;
- else
- throw value;
- },
-
- getCurrentFrameKeys: function(context)
- {
- var globals = keys(context.window.wrappedJSObject); // return is safe
-
- if (context.currentFrame)
- return this.getFrameKeys(context.currentFrame, globals);
-
- return globals;
- },
-
- getFrameKeys: function(frame, names)
- {
- var listValue = {value: null}, lengthValue = {value: 0};
- frame.scope.getProperties(listValue, lengthValue);
-
- for (var i = 0; i < lengthValue.value; ++i)
- {
- var prop = listValue.value[i];
- var name = prop.name.getWrappedValue();
- names.push(name);
- }
- return names;
- },
-
- focusWatch: function(context)
- {
- if (context.detached)
- context.chrome.focus();
- else
- Firebug.toggleBar(true);
-
- context.chrome.selectPanel("script");
-
- var watchPanel = context.getPanel("watches", true);
- if (watchPanel)
- {
- Firebug.CommandLine.isNeededGetReady(context);
- watchPanel.editNewWatch();
- }
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- beginInternalOperation: function() // stop debugger operations like breakOnErrors
- {
- var state = {breakOnErrors: Firebug.breakOnErrors};
- Firebug.breakOnErrors = false;
- return state;
- },
-
- endInternalOperation: function(state) // pass back the object given by beginInternalOperation
- {
- Firebug.breakOnErrors = state.breakOnErrors;
- return true;
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- halt: function(fn)
- {
- this.haltCallback = fn;
- fbs.halt(this);
-
- debugger; // For some reason this is not reliable.
- if (this.haltCallback) // so we have a second try
- {
- if (Firebug.CommandLine.isNeededGetReady(FirebugContext))
- Firebug.CommandLine.evaluate("debugger;", FirebugContext);
- }
-
- },
-
- stop: function(context, frame, type, rv)
- {
- if (context.stopped)
- return RETURN_CONTINUE;
-
- if (!this.isEnabled(context))
- return RETURN_CONTINUE;
-
- var executionContext;
- try
- {
- executionContext = frame.executionContext;
- }
- catch (exc)
- {
- // Can't proceed with an execution context - it happens sometimes.
- return RETURN_CONTINUE;
- }
-
- context.debugFrame = frame;
- context.stopped = true;
-
- var hookReturn = dispatch2(listeners,"onStop",[context,frame, type,rv]);
- if ( hookReturn && hookReturn >= 0 )
- {
- delete context.stopped;
- delete context.debugFrame;
- delete context;
- return hookReturn;
- }
-
- try {
- executionContext.scriptsEnabled = false;
-
- cacheAllScripts(context);
-
- } catch (exc) {
- // This attribute is only valid for contexts which implement nsIScriptContext.
- }
-
- try
- {
- // We will pause here until resume is called
- var depth = fbs.enterNestedEventLoop({onNest: bindFixed(this.startDebugging, this, context)});
- // For some reason we don't always end up here
- }
- catch (exc)
- {
- // Just ignore exceptions that happened while in the nested loop
- }
-
- try {
- if (executionContext.isValid)
- {
- executionContext.scriptsEnabled = true;
- }
- else
- {
- }
- } catch (exc) {
- }
-
- this.stopDebugging(context);
-
- dispatch(listeners,"onResume",[context]);
-
- if (this.aborted)
- {
- delete this.aborted;
- return RETURN_ABORT;
- }
- else
- return RETURN_CONTINUE;
- },
-
- resume: function(context)
- {
- if (!context.stopped)
- {
- this.syncCommands(context);
- return;
- }
-
- delete context.stopped;
- delete context.debugFrame;
- delete context.currentFrame;
- delete context;
-
- var depth = fbs.exitNestedEventLoop();
- },
-
- abort: function(context)
- {
- if (context.stopped)
- {
- context.aborted = true;
- this.resume(context);
- }
- },
-
- stepOver: function(context)
- {
- if (!context.debugFrame || !context.debugFrame.isValid)
- return;
-
- fbs.step(STEP_OVER, context.debugFrame);
- this.resume(context);
- },
-
- stepInto: function(context)
- {
- if (!context.debugFrame.isValid)
- return;
-
- fbs.step(STEP_INTO, context.debugFrame);
- this.resume(context);
- },
-
- stepOut: function(context)
- {
- if (!context.debugFrame.isValid)
- return;
-
- fbs.step(STEP_OUT, context.debugFrame);
- this.resume(context);
- },
-
- suspend: function(context)
- {
- if (context.stopped)
- return;
- fbs.suspend();
- },
-
- runUntil: function(context, sourceFile, lineNo)
- {
- if (!context.debugFrame.isValid)
- return;
-
- fbs.runUntil(sourceFile, lineNo, context.debugFrame, this);
- this.resume(context);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Breakpoints
-
- setBreakpoint: function(sourceFile, lineNo)
- {
- fbs.setBreakpoint(sourceFile, lineNo, null, Firebug.Debugger);
- },
-
- clearBreakpoint: function(sourceFile, lineNo)
- {
- fbs.clearBreakpoint(sourceFile.href, lineNo);
- },
-
- setErrorBreakpoint: function(sourceFile, line)
- {
- fbs.setErrorBreakpoint(sourceFile, line, Firebug.Debugger);
- },
-
- clearErrorBreakpoint: function(sourceFile, line)
- {
- fbs.clearErrorBreakpoint(sourceFile.href, line, Firebug.Debugger);
- },
-
- enableErrorBreakpoint: function(sourceFile, line)
- {
- fbs.enableErrorBreakpoint(sourceFile, line, Firebug.Debugger);
- },
-
- disableErrorBreakpoint: function(sourceFile, line)
- {
- fbs.disableErrorBreakpoint(sourceFile, line, Firebug.Debugger);
- },
-
- clearAllBreakpoints: function(context)
- {
- var sourceFiles = sourceFilesAsArray(context);
- fbs.clearAllBreakpoints(sourceFiles, Firebug.Debugger);
- },
-
- enableAllBreakpoints: function(context)
- {
- for (var url in context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url, {call: function(url, lineNo)
- {
- fbs.enableBreakpoint(url, lineNo);
- }});
- }
- },
-
- disableAllBreakpoints: function(context)
- {
- for (var url in context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url, {call: function(url, lineNo)
- {
- fbs.disableBreakpoint(url, lineNo);
- }});
- }
- },
-
- getBreakpointCount: function(context)
- {
- var count = 0;
- for (var url in context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url,
- {
- call: function(url, lineNo)
- {
- ++count;
- }
- });
-
- fbs.enumerateErrorBreakpoints(url,
- {
- call: function(url, lineNo)
- {
- ++count;
- }
- });
- }
- return count;
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // Debugging and monitoring
-
- trace: function(fn, object, mode)
- {
- if (typeof(fn) == "function" || fn instanceof Function)
- {
- var script = findScriptForFunctionInContext(FirebugContext, fn);
- if (script)
- this.traceFunction(fn, script, mode);
- }
- },
-
- untrace: function(fn, object, mode)
- {
- if (typeof(fn) == "function" || fn instanceof Function)
- {
- var script = findScriptForFunctionInContext(FirebugContext, fn);
- if (script)
- this.untraceFunction(fn, script, mode);
- }
- },
-
- traceFunction: function(fn, script, mode)
- {
- var scriptInfo = getSourceFileAndLineByScript(FirebugContext, script);
- if (scriptInfo)
- {
- if (mode == "debug")
- this.setBreakpoint(scriptInfo.sourceFile, scriptInfo.lineNo, null, this);
- else if (mode == "monitor")
- fbs.monitor(scriptInfo.sourceFile, scriptInfo.lineNo, Firebug.Debugger);
- }
- },
-
- untraceFunction: function(fn, script, mode)
- {
- var scriptInfo = getSourceFileAndLineByScript(FirebugContext, script);
- if (scriptInfo)
- {
- if (mode == "debug")
- this.clearBreakpoint(scriptInfo.sourceFile, scriptInfo.lineNo);
- else if (mode == "monitor")
- fbs.unmonitor(scriptInfo.sourceFile, scriptInfo.lineNo);
- }
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // UI Stuff
-
- startDebugging: function(context)
- {
- try {
- fbs.lockDebugger();
-
- context.currentFrame = context.debugFrame;
-
- // Make FirebugContext = context and sync the UI
- var browser = context.browser;
- browser.chrome.showContext(browser, context);
-
- this.syncCommands(context);
- this.syncListeners(context);
-
- const updateViewOnShowHook = function()
- {
- Firebug.toggleBar(true);
-
- FirebugChrome.select(context.currentFrame, "script");
-
- var stackPanel = context.getPanel("callstack");
- if (stackPanel)
- stackPanel.refresh(context);
-
- context.chrome.focus();
- }
- if ( !context.hideDebuggerUI || (FirebugChrome.getCurrentBrowser() && FirebugChrome.getCurrentBrowser().showFirebug))
- updateViewOnShowHook();
- else {
- context.chrome.updateViewOnShowHook = updateViewOnShowHook;
- }
-
- }
- catch(exc)
- {
- }
- },
-
- stopDebugging: function(context)
- {
- try
- {
- fbs.unlockDebugger();
-
- // If the user reloads the page while the debugger is stopped, then
- // the current context will be destroyed just before
- if (context && context.window)
- {
- var chrome = context.chrome;
- if (!chrome)
- chrome = FirebugChrome;
-
- if ( chrome.updateViewOnShowHook )
- delete chrome.updateViewOnShowHook;
-
- this.syncCommands(context);
- this.syncListeners(context);
-
- if (FirebugContext && !FirebugContext.panelName) // XXXjjb all I know is that syncSidePanels() needs this set
- FirebugContext.panelName = "script";
-
- chrome.syncSidePanels();
-
- var panel = context.getPanel("script", true);
- if (panel)
- {
- panel.showNoStackFrame();
- panel.select(null);
- }
- }
- }
- catch (exc)
- {
- ERROR(exc);
- }
- },
-
- syncCommands: function(context)
- {
- var chrome = context.chrome;
- if (!chrome)
- {
- return;
- }
-
- if (context.stopped)
- {
- chrome.setGlobalAttribute("fbDebuggerButtons", "stopped", "true");
- chrome.setGlobalAttribute("cmd_resumeExecution", "disabled", "false");
- chrome.setGlobalAttribute("cmd_stepOver", "disabled", "false");
- chrome.setGlobalAttribute("cmd_stepInto", "disabled", "false");
- chrome.setGlobalAttribute("cmd_stepOut", "disabled", "false");
- }
- else
- {
- chrome.setGlobalAttribute("fbDebuggerButtons", "stopped", "true");
- chrome.setGlobalAttribute("cmd_resumeExecution", "disabled", "true");
- chrome.setGlobalAttribute("cmd_stepOver", "disabled", "true");
- chrome.setGlobalAttribute("cmd_stepInto", "disabled", "true");
- chrome.setGlobalAttribute("cmd_stepOut", "disabled", "true");
- }
- },
-
- syncListeners: function(context)
- {
- var chrome = context.chrome;
- if (!chrome)
- chrome = FirebugChrome;
-
- if (context.stopped)
- this.attachListeners(context, chrome);
- else
- this.detachListeners(context, chrome);
- },
-
- attachListeners: function(context, chrome)
- {
- this.keyListeners =
- [
- chrome.keyCodeListen("F8", null, bind(this.resume, this, context), true),
- chrome.keyListen("/", isControl, bind(this.resume, this, context)),
- chrome.keyCodeListen("F10", null, bind(this.stepOver, this, context), true),
- chrome.keyListen("'", isControl, bind(this.stepOver, this, context)),
- chrome.keyCodeListen("F11", null, bind(this.stepInto, this, context)),
- chrome.keyListen(";", isControl, bind(this.stepInto, this, context)),
- chrome.keyCodeListen("F11", isShift, bind(this.stepOut, this, context)),
- chrome.keyListen(",", isControlShift, bind(this.stepOut, this, context))
- ];
- },
-
- detachListeners: function(context, chrome)
- {
- if (this.keyListeners)
- {
- for (var i = 0; i < this.keyListeners.length; ++i)
- chrome.keyIgnore(this.keyListeners[i]);
- delete this.keyListeners;
- }
- },
-
- showPanel: function(browser, panel)
- {
- var chrome = browser.chrome;
- if (chrome.updateViewOnShowHook)
- {
- var updateViewOnShowHook = chrome.updateViewOnShowHook;
- delete chrome.updateViewOnShowHook;
- updateViewOnShowHook();
- }
-
- if (panel)
- {
- this.syncCommands(panel.context);
- this.ableWatchSidePanel(panel.context);
- }
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // These are XUL window level call backs and should be moved into Firebug where is says nsIFirebugClient
-
- onJSDActivate: function(jsd) // just before hooks are set
- {
- // this is just to get the timing right.
- // we called by fbs as a "debuggr", (one per window) and we are re-dispatching to our listeners,
- // Firebug.DebugListeners.
- var active = this.setIsJSDActive();
-
- dispatch2(listeners,"onJSDActivate",[fbs]);
- },
-
- onJSDDeactivate: function(jsd)
- {
- this.setIsJSDActive();
- dispatch2(listeners,"onJSDDeactivate",[fbs]);
- },
-
- setIsJSDActive: function()
- {
- var active = fbs.isJSDActive();
- if (active)
- $('fbStatusIcon').setAttribute("jsd", "on");
- else
- $('fbStatusIcon').setAttribute("jsd", "off");
-
- return active;
- },
-
- suspendFirebug: function()
- {
- Firebug.suspendFirebug();
- },
-
- resumeFirebug: function()
- {
- Firebug.resumeFirebug();
- },
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- supportsWindow: function(win)
- {
- var context = ( (win && TabWatcher) ? TabWatcher.getContextByWindow(win) : null);
-
- if (!this.isEnabled(context))
- return false;
-
- this.breakContext = context;
- return !!context;
- },
-
- supportsGlobal: function(global) // This is call from fbs for almost all fbs operations
- {
- var context = (TabWatcher ? TabWatcher.getContextByWindow(global) : null);
-
- if (context)
- {
- // Apparently the global is a XPCSafeJSObjectWrapper that looks like a Window.
- // Since this is method called a lot make a hacky fast check on _getFirebugConsoleElement
- if (!global._getFirebugConsoleElement)
- {
- if (Firebug.Console.isEnabled(context))
- {
- var consoleReady = Firebug.Console.isNeededGetReady(context, global);
- }
- else
- {
- }
- }
-
- if (!this.isEnabled(context))
- return false;
- }
-
- this.breakContext = context;
- return !!context;
- },
-
- onLock: function(state)
- {
- // XXXjoe For now, trying to see if it's ok to have multiple contexts
- // debugging simultaneously - otherwise we need this
- //if (this.context != this.debugContext)
- {
- // XXXjoe Disable step/continue buttons
- }
- },
-
- onBreak: function(frame, type)
- {
- try {
- var context = this.breakContext;
- delete this.breakContext;
-
- if (!context)
- context = getFrameContext(frame);
- if (!context)
- return RETURN_CONTINUE;
-
- return this.stop(context, frame, type);
- }
- catch (exc)
- {
- throw exc;
- }
- },
-
- onHalt: function(frame)
- {
- var callback = this.haltCallback;
- delete this.haltCallback;
-
- if (callback)
- callback(frame);
-
- return RETURN_CONTINUE;
- },
-
- onThrow: function(frame, rv)
- {
- // onThrow is called for throw and for any catch that does not succeed.
- var context = this.breakContext;
- delete this.breakContext;
-
- if (!context)
- {
- FBTrace.sysout("debugger.onThrow, no context, try to get from frame\n");
- context = getFrameContext(frame);
- }
- if (!context)
- return RETURN_CONTINUE_THROW;
-
- if (!fbs.trackThrowCatch)
- return RETURN_CONTINUE_THROW;
-
- try
- {
- var isCatch = this.isCatchFromPreviousThrow(frame, context);
- if (!isCatch)
- {
- context.thrownStackTrace = getStackTrace(frame, context);
- }
- else
- {
- }
- }
- catch (exc)
- {
- FBTrace.sysout("onThrow FAILS: "+exc+"\n");
- }
-
- if (dispatch2(listeners,"onThrow",[context, frame, rv]))
- return this.stop(context, frame, TYPE_THROW, rv);
- return RETURN_CONTINUE_THROW;
- },
-
- isCatchFromPreviousThrow: function(frame, context)
- {
- if (context.thrownStackTrace)
- {
- var trace = context.thrownStackTrace.frames;
- if (trace.length > 1) // top of stack is [0]
- {
- var curFrame = frame;
- var curFrameSig = curFrame.script.tag +"."+curFrame.pc;
- for (var i = 1; i < trace.length; i++)
- {
- var preFrameSig = trace[i].signature();
- if (curFrameSig == preFrameSig)
- {
- return true; // catch from previous throw (or do we need to compare whole stack?
- }
- }
- // We looked at the previous stack and did not match the current frame
- }
- }
- return false;
- },
-
- onCall: function(frame)
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- if (!context)
- context = getFrameContext(frame);
- if (!context)
- return RETURN_CONTINUE;
-
- frame = getStackFrame(frame, context);
- Firebug.Console.log(frame, context);
- },
-
- onError: function(frame, error)
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- try
- {
- Firebug.errorStackTrace = getStackTrace(frame, context);
- if (Firebug.breakOnErrors)
- Firebug.Errors.showMessageOnStatusBar(error);
- }
- catch (exc) {
- }
-
- var hookReturn = dispatch2(listeners,"onError",[context, frame, error]);
-
- if (Firebug.breakOnErrors)
- return -1; // break
-
- if (hookReturn)
- return hookReturn;
-
- return -2; /* let firebug service decide to break or not */
- },
-
- onEvalScriptCreated: function(frame, outerScript, innerScripts)
- {
- try
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- var sourceFile = this.getEvalLevelSourceFile(frame, context, innerScripts);
-
- dispatch(listeners,"onEvalScriptCreated",[context, frame, sourceFile.href]);
- return sourceFile;
- }
- catch (e)
- {
- }
- },
-
- onEventScriptCreated: function(frame, outerScript, innerScripts)
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- var script = frame.script;
- var creatorURL = normalizeURL(frame.script.fileName);
-
- try {
- var source = script.functionSource;
- } catch (exc) {
- /*Bug 426692 */
- var source = creatorURL + "/"+getUniqueId();
- }
-
- var url = this.getDynamicURL(frame, source, "event");
-
- var lines = context.sourceCache.store(url, source);
- var sourceFile = new FBL.EventSourceFile(url, frame.script, "event:"+script.functionName+"."+script.tag, lines, innerScripts);
- context.sourceFileMap[url] = sourceFile;
-
- dispatch(listeners,"onEventScriptCreated",[context, frame, url]);
- return sourceFile;
- },
-
- // We just compiled a bunch of JS, eg a script tag in HTML. We are about to run the outerScript.
- onTopLevelScriptCreated: function(frame, outerScript, innerScripts)
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- // This is our only chance to get the linetable for the outerScript since it will run and be GC next.
- var script = frame.script;
- var url = normalizeURL(script.fileName);
-
- var sourceFile = context.sourceFileMap[url];
- if (sourceFile && (sourceFile instanceof FBL.TopLevelSourceFile) ) // TODO test multiple script tags in one html file
- {
- if (!sourceFile.outerScript || !sourceFile.outerScript.isValid)
- sourceFile.outerScript = outerScript;
- FBL.addScriptsToSourceFile(sourceFile, outerScript, innerScripts);
- }
- else
- {
- sourceFile = new FBL.TopLevelSourceFile(url, script, script.lineExtent, innerScripts);
- context.sourceFileMap[url] = sourceFile;
- }
-
- dispatch(listeners,"onTopLevelScriptCreated",[context, frame, sourceFile.href]);
- return sourceFile;
- },
-
-
- onToggleBreakpoint: function(url, lineNo, isSet, props)
- {
- if (props.debugger != this) // then not for us
- {
- return;
- }
-
- for (var i = 0; i < TabWatcher.contexts.length; ++i)
- {
- var panel = TabWatcher.contexts[i].getPanel("script", true);
- if (panel)
- {
- panel.context.invalidatePanels("breakpoints");
-
- var sourceBox = panel.getSourceBoxByURL(url);
- if (sourceBox)
- {
- var row = sourceBox.getLineNode(lineNo);
- if (!row)
- continue; // we *should* only be called for lines in the viewport...
-
- row.setAttribute("breakpoint", isSet);
- if (isSet && props)
- {
- row.setAttribute("condition", props.condition ? "true" : "false");
- row.setAttribute("disabledBreakpoint", new Boolean(props.disabled).toString());
- } else
- {
- row.removeAttribute("condition");
- row.removeAttribute("disabledBreakpoint");
- }
- }
- else
- {
- }
- }
- }
- },
-
- onToggleErrorBreakpoint: function(url, lineNo, isSet)
- {
- for (var i = 0; i < TabWatcher.contexts.length; ++i)
- {
- var panel = TabWatcher.contexts[i].getPanel("console", true);
- if (panel)
- {
- panel.context.invalidatePanels("breakpoints");
-
- for (var row = panel.panelNode.firstChild; row; row = row.nextSibling)
- {
- var error = row.firstChild.repObject;
- if (error instanceof ErrorMessage && error.href == url && error.lineNo == lineNo)
- {
- if (isSet)
- setClass(row.firstChild, "breakForError");
- else
- removeClass(row.firstChild, "breakForError");
- }
- }
- }
- }
- },
-
- onToggleMonitor: function(url, lineNo, isSet)
- {
- for (var i = 0; i < TabWatcher.contexts.length; ++i)
- {
- var panel = TabWatcher.contexts[i].getPanel("console", true);
- if (panel)
- panel.context.invalidatePanels("breakpoints");
- }
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // XXXjjb this code is not called, because I found the scheme for detecting Function too complex.
- // I'm leaving it here to remind us that we need to support new Function().
- onFunctionConstructor: function(frame, ctor_script)
- {
- try
- {
- var context = this.breakContext;
- delete this.breakContext;
-
- var sourceFile = this.createSourceFileForFunctionConstructor(frame, ctor_script, context);
-
- dispatch(listeners,"onFunctionConstructor",[context, frame, ctor_script, sourceFile.href]);
- return sourceFile.href;
- }
- catch(exc)
- {
- ERROR("debugger.onFunctionConstructor failed: "+exc);
- return null;
- }
-
- },
-
- createSourceFileForFunctionConstructor: function(caller_frame, ctor_script, context)
- {
- var ctor_expr = null; // this.getConstructorExpression(caller_frame, context);
- if (ctor_expr)
- var source = this.getEvalBody(caller_frame, "lib.createSourceFileForFunctionConstructor ctor_expr", 1, ctor_expr);
- else
- var source = " bah createSourceFileForFunctionConstructor"; //ctor_script.functionSource;
-
- var url = this.getDynamicURL(frame, source, "Function");
-
- var lines = context.sourceCache.store(url, source);
- var sourceFile = new FBL.FunctionConstructorSourceFile(url, caller_frame.script, ctor_expr, lines.length);
- context.sourceFileMap[url] = sourceFile;
-
- return sourceFile;
- },
-
- getConstructorExpression: function(caller_frame, context)
- {
- // We believe we are just after the ctor call.
- var decompiled_lineno = getLineAtPC(caller_frame, context);
- var decompiled_lines = splitLines(caller_frame.script.functionSource); // TODO place in sourceCache?
- var candidate_line = decompiled_lines[decompiled_lineno - 1]; // zero origin
- if (candidate_line && candidate_line != null)
- {
- var m = reFunction.exec(candidate_line);
- if (m)
- var arguments = m[1]; // TODO Lame: need to count parens, with escapes and quotes
- }
- if (arguments) // need to break down commas and get last arg.
- {
- var lastComma = arguments.lastIndexOf(',');
- return arguments.substring(lastComma+1); // if -1 then 0
- }
- return null;
- },
- // end of guilt trip
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- // Called by debugger.onEval() to store eval() source.
- // The frame has the blank-function-name script and it is not the top frame.
- // The frame.script.fileName is given by spidermonkey as file of the first eval().
- // The frame.script.baseLineNumber is given by spidermonkey as the line of the first eval() call
- // The source that contains the eval() call is the source of our caller.
- // If our caller is a file, the source of our caller is at frame.script.baseLineNumber
- // If our caller is an eval, the source of our caller is TODO Check Test Case
-
- getEvalLevelSourceFile: function(frame, context, innerScripts)
- {
- var eval_expr = this.getEvalExpression(frame, context);
- var source = this.getEvalBody(frame, "lib.getEvalLevelSourceFile.getEvalBody", 1, eval_expr);
- if (context.onReadySpy) // coool we can get the request URL.
- {
- var url = context.onReadySpy.getURL();
- }
- else
- var url = this.getDynamicURL(frame, source, "eval");
-
- var lines = context.sourceCache.store(url, source);
- var sourceFile = new FBL.EvalLevelSourceFile(url, frame.script, eval_expr, lines, innerScripts);
- context.sourceFileMap[url] = sourceFile;
- return sourceFile;
- },
-
- getDynamicURL: function(frame, source, kind)
- {
- var url = this.getURLFromLastLine(source);
- if (url)
- url.kind = "source";
- else
- {
- var callerURL = normalizeURL(frame.script.fileName);
- var url = this.getURLFromMD5(callerURL, source, kind);
- if (url)
- url.kind = "MD5";
- else
- {
- var url = this.getDataURLForScript(frame.script, source);
- url.kind = "data";
- }
- }
-
- return url;
- },
-
- getURLFromLastLine: function(source)
- {
- // Ignores any trailing whitespace in |source|
- const reURIinComment = /\/\/@\ssourceURL=\s*(\S*?)\s*$/m;
- var m = reURIinComment.exec(source);
- if (m)
- return m[1];
- },
-
- getURLFromMD5: function(callerURL, source, kind)
- {
- this.hash_service.init(this.nsICryptoHash.MD5);
- byteArray = [];
- for (var j = 0; j < source.length; j++)
- {
- byteArray.push( source.charCodeAt(j) );
- }
- this.hash_service.update(byteArray, byteArray.length);
- var hash = this.hash_service.finish(true);
-
- // encoding the hash should be ok, it should be information-preserving? Or at least reversable?
- var url = callerURL + (kind ? "/"+kind+"/" : "/") + encodeURIComponent(hash);
-
- return url;
- },
-
- getEvalExpression: function(frame, context)
- {
- var expr = this.getEvalExpressionFromEval(frame, context); // eval in eval
-
- return (expr) ? expr : this.getEvalExpressionFromFile(normalizeURL(frame.script.fileName), frame.script.baseLineNumber, context);
- },
-
- getEvalExpressionFromFile: function(url, lineNo, context)
- {
- if (context && context.sourceCache)
- {
- var in_url = FBL.reJavascript.exec(url);
- if (in_url)
- {
- var m = reEval.exec(in_url[1]);
- if (m)
- return m[1];
- else
- return null;
- }
-
- var htm = reHTM.exec(url);
- if (htm) {
- lineNo = lineNo + 1; // embedded scripts seem to be off by one? XXXjjb heuristic
- }
- // Walk backwards from the first line in the function until we find the line which
- // matches the pattern above, which is the eval call
- var line = "";
- for (var i = 0; i < 3; ++i)
- {
- line = context.sourceCache.getLine(url, lineNo-i) + line;
- if (line && line != null)
- {
- var m = reEval.exec(line);
- if (m)
- return m[1];
- }
- }
- }
- return null;
- },
-
- getEvalExpressionFromEval: function(frame, context)
- {
- var callingFrame = frame.callingFrame;
- var sourceFile = FBL.getSourceFileByScript(context, callingFrame.script);
- if (sourceFile)
- {
- var lineNo = callingFrame.script.pcToLine(callingFrame.pc, PCMAP_SOURCETEXT);
- lineNo = lineNo - callingFrame.script.baseLineNumber + 1;
- var url = sourceFile.href;
-
- var line = "";
- for (var i = 0; i < 3; ++i)
- {
- line = context.sourceCache.getLine(url, lineNo-i) + line;
- if (line && line != null)
- {
- var m = reEval.exec(line);
- if (m)
- return m[1]; // TODO Lame: need to count parens, with escapes and quotes
- }
- }
- }
- return null;
- },
-
- getEvalBody: function(frame, asName, asLine, evalExpr)
- {
- if (evalExpr)
- {
- var result_src = {};
- var evalThis = "new String("+evalExpr+");";
- var evaled = frame.eval(evalThis, asName, asLine, result_src);
-
- if (evaled)
- {
- var src = result_src.value.getWrappedValue();
- return src;
- }
- else
- {
- var source;
- if(evalExpr == "function(p,a,c,k,e,r")
- source = "/packer/ JS compressor detected";
- else
- source = frame.script.functionSource;
- return source+" /* !eval("+evalThis+")) */";
- }
- }
- else
- {
- return frame.script.functionSource; // XXXms - possible crash on OSX
- }
- },
-
- getDataURLForScript: function(script, source)
- {
- if (!source)
- return "eval."+script.tag;
-
- // data:text/javascript;fileName=x%2Cy.js;baseLineNumber=10,<the-url-encoded-data>
- var uri = "data:text/javascript;";
- uri += "fileName="+encodeURIComponent(script.fileName) + ";";
- uri += "baseLineNumber="+encodeURIComponent(script.baseLineNumber) + ","
- uri += encodeURIComponent(source);
-
- return uri;
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Module
-
- initialize: function()
- {
- this.nsICryptoHash = Components.interfaces["nsICryptoHash"];
-
- this.debuggerName = window.location.href+"--"+FBL.getUniqueId(); /*@explore*/
- this.toString = function() { return this.debuggerName; } /*@explore*/
- this.hash_service = CCSV("@mozilla.org/security/hash;1", "nsICryptoHash");
-
- $("cmd_breakOnErrors").setAttribute("checked", Firebug.breakOnErrors);
- $("cmd_breakOnTopLevel").setAttribute("checked", Firebug.breakOnTopLevel);
-
- this.wrappedJSObject = this; // how we communicate with fbs
- this.panelName = "script";
- this.description = $STR("script.modulemanager.description");
-
- // This is a service operation, a way of encapsulating fbs which is in turn implementing this
- // simple service. We could implment a whole component for this service, but it hardly makes sense.
- Firebug.broadcast = function encapsulateFBSBroadcast(message, args)
- {
- fbs.broadcast(message, args);
- }
-
- Firebug.ActivableModule.initialize.apply(this, arguments);
- },
-
- initializeUI: function()
- {
- Firebug.ActivableModule.initializeUI.apply(this, arguments);
- this.filterButton = $("fbScriptFilterMenu");
- this.filterMenuUpdate();
- fbs.registerClient(this); // allow callbacks for jsd
- // 1.3.1 move fbs.registerDebugger(this); // this will eventually set 'jsd' on the statusIcon
- },
-
- initContext: function(context)
- {
- Firebug.ActivableModule.initContext.apply(this, arguments);
- },
-
- reattachContext: function(browser, context)
- {
- var chrome = context ? context.chrome : FirebugChrome;
- this.filterButton = chrome.$("fbScriptFilterMenu"); // connect to the button in the new window, not 'window'
- this.filterMenuUpdate();
- Firebug.ActivableModule.reattachContext.apply(this, arguments);
- },
-
- loadedContext: function(context)
- {
- var watchPanel = this.ableWatchSidePanel(context);
- var needNow = watchPanel && watchPanel.watches;
- var watchPanelState = Firebug.getPanelState({name: "watches", context: context});
- var needPersistent = watchPanelState && watchPanelState.watches;
- if (needNow || needPersistent)
- {
- Firebug.CommandLine.isNeededGetReady(context);
- if (watchPanel)
- {
- context.setTimeout(function refreshWatchesAfterCommandLineReady()
- {
- watchPanel.refresh();
- });
- }
- }
- else
- {
- }
-
- updateScriptFiles(context);
-
- var panel = context.chrome.getSelectedPanel();
- if (panel && panel.name == "script" && panel.restoreRetry)
- {
- panel.location = null; // the default could have been a URLOnly
- var state = Firebug.getPanelState(panel);
- panel.reShow(state);
- delete panel.restoreRetry;
- }
- },
-
- destroyContext: function(context, persistedState)
- {
- Firebug.ActivableModule.destroyContext.apply(this, arguments);
-
- if (context.stopped)
- {
- TabWatcher.cancelNextLoad = true;
- this.abort(context);
- }
- },
-
- updateOption: function(name, value)
- {
- if (name == "breakOnErrors")
- $("cmd_breakOnErrors").setAttribute("checked", value);
- else if (name == "breakOnTopLevel")
- $("cmd_breakOnTopLevel").setAttribute("checked", value);
- },
-
- getObjectByURL: function(context, url)
- {
- var sourceFile = getScriptFileByHref(url, context);
- if (sourceFile)
- return new SourceLink(sourceFile.href, 0, "js");
- },
-
- addListener: function(listener)
- {
- listeners.push(listener);
- },
-
- removeListener: function(listener)
- {
- remove(listeners, listener);
- },
-
- shutdown: function()
- {
- fbs.unregisterDebugger(this);
- fbs.unregisterClient(this);
- },
-
- registerDebugger: function() // 1.3.1 safe for multiple calls
- {
- if (this.registered)
- return;
- var check = fbs.registerDebugger(this); // this will eventually set 'jsd' on the statusIcon
- this.registered = true;
- },
-
- unregisterDebugger: function() // 1.3.1 safe for multiple calls
- {
- if (!this.registered)
- return;
- if (Firebug.Debugger.activeContexts.length > 0 || Firebug.Console.activeContexts.length > 0)
- return; // don't turn off JSD unless both console and script panels are done.
- var check = fbs.unregisterDebugger(this);
- this.registered = false;
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends ActivableModule
- onFirstPanelActivate: function(context, init)
- {
- this.registerDebugger(); // 1.3.1
- },
-
- onPanelActivate: function(context, init, panelName)
- {
- //if (panelName == "console" || panelName == this.panelName)
- // this.ableWatchSidePanel(context);
-
- if (panelName != this.panelName)
- return;
-
- if (!init)
- context.window.location.reload();
- },
-
- onPanelDeactivate: function(context, destroy, panelName)
- {
- if (panelName != this.panelName)
- return;
-
- if (!destroy) // then the user is saying no to debugging
- this.clearAllBreakpoints(context);
- // else the context is being torn down, possibly to reload
- },
-
- onLastPanelDeactivate: function(context, destroy)
- {
- this.unregisterDebugger(); // 1.3.1
- },
-
- onSuspendFirebug: function(context)
- {
- fbs.pause(); // can be called multiple times.
- var active = this.setIsJSDActive(); // update ui
-
- },
-
- onResumeFirebug: function(context)
- {
- fbs.unPause();
- var active = this.setIsJSDActive(); // update ui
-
- },
-
- ableWatchSidePanel: function(context)
- {
- if (Firebug.Console.isEnabled(context))
- {
- var watchPanel = context.getPanel("watches", true);
- if (watchPanel)
- watchPanel.enablePanel();
- return watchPanel;
- }
- else
- {
- var watchPanel = context.getPanel("watches", true);
- if (watchPanel)
- watchPanel.disablePanel();
- return false;
- }
- },
-
- //---------------------------------------------------------------------------------------------
- // Menu in toolbar.
-
- onScriptFilterMenuTooltipShowing: function(tooltip, context)
- {
- },
-
- onScriptFilterMenuCommand: function(event, context)
- {
- var menu = event.target;
- Firebug.setPref(Firebug.servicePrefDomain, "scriptsFilter", menu.value);
- Firebug.Debugger.filterMenuUpdate();
- },
-
- menuFullLabel:
- {
- static: $STR("ScriptsFilterStatic"),
- evals: $STR("ScriptsFilterEval"),
- events: $STR("ScriptsFilterEvent"),
- all: $STR("ScriptsFilterAll"),
- },
-
- menuShortLabel:
- {
- static: $STR("ScriptsFilterStaticShort"),
- evals: $STR("ScriptsFilterEvalShort"),
- events: $STR("ScriptsFilterEventShort"),
- all: $STR("ScriptsFilterAllShort"),
- },
-
- onScriptFilterMenuPopupShowing: function(menu, context)
- {
- if (this.menuTooltip)
- this.menuTooltip.fbEnabled = false;
-
- var items = menu.getElementsByTagName("menuitem");
- var value = this.filterButton.value;
-
- for (var i=0; i<items.length; i++)
- {
- var option = items[i].value;
- if (!option)
- continue;
-
- if (option == value)
- items[i].setAttribute("checked", "true");
-
- items[i].label = Firebug.Debugger.menuFullLabel[option];
- }
-
- return true;
- },
-
- onScriptFilterMenuPopupHiding: function(tooltip, context)
- {
- if (this.menuTooltip)
- this.menuTooltip.fbEnabled = true;
-
- return true;
- },
-
- filterMenuUpdate: function()
- {
- var value = Firebug.getPref(Firebug.servicePrefDomain, "scriptsFilter");
- this.filterButton.value = value;
- this.filterButton.label = this.menuShortLabel[value];
- this.filterButton.removeAttribute("disabled");
- this.filterButton.setAttribute("value", value);
- },
-
- //----------------------------------------------------------------------------------
-
- });
-
-
- // ************************************************************************************************
-
- Firebug.ScriptPanel = function() {};
-
- Firebug.ScriptPanel.prototype = extend(Firebug.SourceBoxPanel,
- {
-
- updateSourceBox: function(sourceBox)
- {
-
- },
-
- getSourceType: function()
- {
- return "js";
- },
-
- getDecorator: function(sourceBox)
- {
- if (!this.decorator)
- this.decorator = bind(this.decorateJavascript, this, sourceBox);
- return this.decorator;
- },
-
- decorateJavascript: function(sourceBox)
- {
- this.markExecutableLines(sourceBox);
- this.setLineBreakpoints(sourceBox.repObject, sourceBox)
- },
-
- showFunction: function(fn)
- {
- var sourceLink = findSourceForFunction(fn, this.context);
- if (sourceLink)
- {
- this.showSourceLink(sourceLink);
- }
- else
- {
- }
- },
-
- showSourceLink: function(sourceLink)
- {
- var sourceFile = getScriptFileByHref(sourceLink.href, this.context);
- if (sourceFile)
- {
- this.navigate(sourceFile);
- if (sourceLink.line)
- this.scrollToLine(sourceLink.href, sourceLink.line, this.jumpHighlightFactory(sourceLink.line, this.context));
- }
- },
-
- showStackFrame: function(frame)
- {
- this.context.currentFrame = frame;
-
- if (!frame || (frame && !frame.isValid))
- {
- this.showNoStackFrame();
- return;
- }
-
- this.executionFile = FBL.getSourceFileByScript(this.context, frame.script);
- if (this.executionFile)
- {
- var url = this.executionFile.href;
- var analyzer = this.executionFile.getScriptAnalyzer(frame.script);
- this.executionLineNo = analyzer.getSourceLineFromFrame(this.context, frame); // TODo implement for each type
- this.navigate(this.executionFile);
- this.scrollToLine(url, this.executionLineNo, bind(this.highlightExecutionLine, this) );
- this.context.throttle(this.updateInfoTip, this);
- return;
- }
- else
- {
- this.showNoStackFrame();
- }
- },
-
- showNoStackFrame: function()
- {
- this.executionFile = null;
- this.executionLineNo = -1;
- this.highlightExecutionLine(this.selectedSourceBox);
- this.updateInfoTip();
- },
-
- markExecutableLines: function(sourceBox)
- {
- var sourceFile = sourceBox.repObject;
- var lineNo = sourceBox.firstViewableLine;
- while( lineNode = sourceBox.getLineNode(lineNo) )
- {
- var script = sourceFile.scriptsIfLineCouldBeExecutable(lineNo, true);
-
- if (script)
- lineNode.setAttribute("executable", "true");
- else
- lineNode.removeAttribute("executable");
-
- lineNo++;
- }
- },
-
- highlightExecutionLine: function(sourceBox)
- {
- if (this.executionLine) // could point to any node in any sourcebox
- this.executionLine.removeAttribute("exeLine");
-
- var lineNode = sourceBox.getLineNode(this.executionLineNo);
-
- this.executionLine = lineNode; // if null, clears
-
- if (lineNode)
- lineNode.setAttribute("exeLine", "true");
- /*@explore*/
- return true; // sticky
- },
-
- toggleBreakpoint: function(lineNo)
- {
- var lineNode = this.selectedSourceBox.getLineNode(lineNo);
- if (lineNode.getAttribute("breakpoint") == "true")
- fbs.clearBreakpoint(this.location.href, lineNo);
- else
- fbs.setBreakpoint(this.location, lineNo, null, Firebug.Debugger);
- },
-
- toggleDisableBreakpoint: function(lineNo)
- {
- var lineNode = this.selectedSourceBox.getLineNode(lineNo);
- if (lineNode.getAttribute("disabledBreakpoint") == "true")
- fbs.enableBreakpoint(this.location.href, lineNo);
- else
- fbs.disableBreakpoint(this.location.href, lineNo);
- },
-
- editBreakpointCondition: function(lineNo)
- {
- var sourceRow = this.selectedSourceBox.getLineNode(lineNo);
- var sourceLine = getChildByClass(sourceRow, "sourceLine");
- var condition = fbs.getBreakpointCondition(this.location.href, lineNo);
-
- Firebug.Editor.startEditing(sourceLine, condition);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- addSelectionWatch: function()
- {
- var watchPanel = this.context.getPanel("watches", true);
- if (watchPanel)
- {
- var selection = this.document.defaultView.getSelection().toString();
- watchPanel.addWatch(selection);
- }
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- updateInfoTip: function()
- {
- var infoTip = this.panelBrowser.infoTip;
- if (infoTip && this.infoTipExpr)
- this.populateInfoTip(infoTip, this.infoTipExpr);
- },
-
- populateInfoTip: function(infoTip, expr)
- {
- if (!expr || isJavaScriptKeyword(expr))
- return false;
-
- var self = this;
- // If the evaluate fails, then we report an error and don't show the infoTip
- Firebug.CommandLine.evaluate(expr, this.context, null, this.context.window,
- function success(result, context)
- {
- var rep = Firebug.getRep(result);
- var tag = rep.shortTag ? rep.shortTag : rep.tag;
-
- tag.replace({object: result}, infoTip);
-
- self.infoTipExpr = expr;
- },
- function failed(result, context)
- {
- self.infoTipExpr = "";
- }
- );
- return (self.infoTipExpr == expr);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // UI event listeners
-
- onMouseDown: function(event)
- {
- var sourceLine = getAncestorByClass(event.target, "sourceLine");
- if (!sourceLine)
- return;
-
- var sourceRow = sourceLine.parentNode;
- var sourceFile = sourceRow.parentNode.repObject;
- var lineNo = parseInt(sourceLine.textContent);
-
- if (isLeftClick(event))
- this.toggleBreakpoint(lineNo);
- else if (isShiftClick(event))
- this.toggleDisableBreakpoint(lineNo);
- else if (isControlClick(event) || isMiddleClick(event))
- {
- Firebug.Debugger.runUntil(this.context, sourceFile, lineNo, Firebug.Debugger);
- cancelEvent(event);
- }
- },
-
- onContextMenu: function(event)
- {
- var sourceLine = getAncestorByClass(event.target, "sourceLine");
- if (!sourceLine)
- return;
-
- var lineNo = parseInt(sourceLine.textContent);
- this.editBreakpointCondition(lineNo);
- cancelEvent(event);
- },
-
- onMouseOver: function(event)
- {
- var sourceLine = getAncestorByClass(event.target, "sourceLine");
- if (sourceLine)
- {
- if (this.hoveredLine)
- removeClass(this.hoveredLine.parentNode, "hovered");
-
- this.hoveredLine = sourceLine;
-
- if (sourceLine)
- setClass(sourceLine.parentNode, "hovered");
- }
- },
-
- onMouseOut: function(event)
- {
- var sourceLine = getAncestorByClass(event.relatedTarget, "sourceLine");
- if (!sourceLine)
- {
- if (this.hoveredLine)
- removeClass(this.hoveredLine.parentNode, "hovered");
-
- delete this.hoveredLine;
- }
- },
-
- onScroll: function(event)
- {
- var scrollingElement = event.target;
- this.reView(scrollingElement);
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
-
- name: "script",
- searchable: true,
-
- initialize: function(context, doc)
- {
- this.onMouseDown = bind(this.onMouseDown, this);
- this.onContextMenu = bind(this.onContextMenu, this);
- this.onMouseOver = bind(this.onMouseOver, this);
- this.onMouseOut = bind(this.onMouseOut, this);
- this.onScroll = bind(this.onScroll, this);
- this.setLineBreakpoints = bind(setLineBreakpoints, this);
-
- this.panelSplitter = $("fbPanelSplitter");
- this.sidePanelDeck = $("fbSidePanelDeck");
-
- Firebug.SourceBoxPanel.initialize.apply(this, arguments);
- },
-
- destroy: function(state)
- {
- delete this.selection; // We want the location (sourcefile) to persist, not the selection (eg stackFrame).
- persistObjects(this, state);
-
- var sourceBox = this.selectedSourceBox;
- state.lastScrollTop = sourceBox && sourceBox.scrollTop
- ? sourceBox.scrollTop
- : this.lastScrollTop;
-
- delete this.selectedSourceBox;
-
- Firebug.SourceBoxPanel.destroy.apply(this, arguments);
- },
-
- detach: function(oldChrome, newChrome)
- {
- if (this.selectedSourceBox)
- this.lastSourceScrollTop = this.selectedSourceBox.scrollTop;
-
- if (this.context.stopped)
- {
- Firebug.Debugger.detachListeners(this.context, oldChrome);
- Firebug.Debugger.attachListeners(this.context, newChrome);
- }
-
- Firebug.Debugger.syncCommands(this.context);
-
- Firebug.SourceBoxPanel.detach.apply(this, arguments);
- },
-
- reattach: function(doc)
- {
- Firebug.SourceBoxPanel.reattach.apply(this, arguments);
-
- setTimeout(bind(function()
- {
- this.selectedSourceBox.scrollTop = this.lastSourceScrollTop;
- delete this.lastSourceScrollTop;
- }, this));
- },
-
- initializeNode: function(oldPanelNode)
- {
- this.tooltip = this.document.createElement("div");
- setClass(this.tooltip, "scriptTooltip");
- obscure(this.tooltip, true);
- this.panelNode.appendChild(this.tooltip);
-
- this.initializeSourceBoxes();
-
- this.panelNode.addEventListener("mousedown", this.onMouseDown, true);
- this.panelNode.addEventListener("contextmenu", this.onContextMenu, false);
- this.panelNode.addEventListener("mouseover", this.onMouseOver, false);
- this.panelNode.addEventListener("mouseout", this.onMouseOut, false);
- this.panelNode.addEventListener("scroll", this.onScroll, true);
- },
-
- destroyNode: function()
- {
- if (this.tooltipTimeout)
- clearTimeout(this.tooltipTimeout);
-
- this.panelNode.removeEventListener("mousedown", this.onMouseDown, true);
- this.panelNode.removeEventListener("contextmenu", this.onContextMenu, false);
- this.panelNode.removeEventListener("mouseover", this.onMouseOver, false);
- this.panelNode.removeEventListener("mouseout", this.onMouseOut, false);
- this.panelNode.removeEventListener("scroll", this.onScroll, true);
- },
-
- clear: function()
- {
- clearNode(this.panelNode);
- },
-
- show: function(state)
- {
- var enabled = Firebug.Debugger.isEnabled(this.context);
-
- // The "enable/disable" button is always visible.
- this.showToolbarButtons("fbScriptButtons", true);
-
- // static scripts can be shown
- this.showToolbarButtons("fbLocationList", true);
-
- // These buttons are visible only if debugger is enabled.
- this.showToolbarButtons("fbLocationSeparator", enabled);
- this.showToolbarButtons("fbDebuggerButtons", enabled);
-
- this.obeyPreferences();
-
- // Additional debugger panels are visible only if debugger
- // is enabled.
- this.panelSplitter.collapsed = !enabled;
- this.sidePanelDeck.collapsed = !enabled;
-
- this.reShow(state);
- },
-
- reShow: function(state)
- {
- this.retryRestore = restoreObjects(this, state, true); // delay the retry for loadedContext
-
- if (state) // then we are restoring
- {
- this.context.throttle(function()
- {
- var sourceBox = this.selectedSourceBox;
- if (sourceBox)
- sourceBox.scrollTop = state.lastScrollTop;
- }, this);
- }
-
- var enabled = Firebug.Debugger.isEnabled(this.context);
- if (enabled)
- {
- Firebug.ModuleManagerPage.hide(this); // the navigate in restoreObject remains in effect
-
- var breakpointPanel = this.context.getPanel("breakpoints", true);
- if (breakpointPanel)
- breakpointPanel.refresh();
- }
- else
- {
- // xxxHonza: ModuleManagerPage should be always displayed if
- // debugger is disabled.
- //if (!state.persistedLocation)
- Firebug.ModuleManagerPage.show(this, Firebug.Debugger);
- // else the navigate in restoreObject remains in effect
- }
- },
-
- obeyPreferences: function()
- {
- if (Firebug.omitObjectPathStack) // User does not want the toolbar stack
- FBL.hide(panelStatus, true);
- },
-
- hide: function(state)
- {
- this.showToolbarButtons("fbDebuggerButtons", false);
- this.showToolbarButtons("fbScriptButtons", false);
- FBL.hide(panelStatus, false);
-
- delete this.infoTipExpr;
-
- var sourceBox = this.selectedSourceBox;
- if (sourceBox && state)
- state.lastScrollTop = sourceBox.scrollTop;
- },
-
- search: function(text)
- {
- var sourceBox = this.selectedSourceBox;
- if (!text || !sourceBox)
- {
- delete this.currentSearch;
- return false;
- }
-
- // Check if the search is for a line number
- var m = reLineNumber.exec(text);
- if (m)
- {
- if (!m[1])
- return true; // Don't beep if only a # has been typed
-
- var lineNo = parseInt(m[1]);
- if (!isNaN(lineNo) && (lineNo > 0) && (lineNo < sourceBox.lines.length) )
- {
- this.scrollToLine(sourceBox.repObject.href, lineNo, this.jumpHighlightFactory(lineNo, this.context))
- return true;
- }
- }
-
- var lineNo = null;
- if (this.currentSearch && text == this.currentSearch.text)
- lineNo = this.currentSearch.findNext(true);
- else
- {
- this.currentSearch = new SourceBoxTextSearch(sourceBox);
- lineNo = this.currentSearch.find(text);
- }
-
- if (lineNo)
- {
- // this lineNo is an zero-based index into sourceBox.lines. Add one for user line numbers
- this.scrollToLine(sourceBox.repObject.href, lineNo, this.jumpHighlightFactory(lineNo+1, this.context));
- //var sel = this.document.defaultView.getSelection();
- //sel.removeAllRanges();
- //sel.addRange(this.currentSearch.range);
-
- //scrollIntoCenterView(row, sourceBox);
- return true;
- }
- else
- return false;
- },
-
- supportsObject: function(object)
- {
- if( object instanceof jsdIStackFrame
- || object instanceof SourceFile
- || (object instanceof SourceLink && object.type == "js")
- || typeof(object) == "function" )
- return 1;
- else return 0;
- },
-
- updateLocation: function(sourceFile)
- {
- if (!Firebug.Debugger.isEnabled(this.context))
- Firebug.ModuleManagerPage.hide(this);
-
- // Since our last use of the sourceFile we may have compiled or recompiled the source
- var updatedSourceFile = this.context.sourceFileMap[sourceFile.href];
- if (!updatedSourceFile)
- updatedSourceFile = this.getDefaultLocation(this.context);
- if (!updatedSourceFile)
- return;
-
- this.showSourceFile(updatedSourceFile);
- },
-
- updateSelection: function(object)
- {
- if (object instanceof jsdIStackFrame)
- this.showStackFrame(object);
- else if (object instanceof SourceFile)
- this.navigate(object);
- else if (object instanceof SourceLink)
- this.showSourceLink(object);
- else if (typeof(object) == "function")
- this.showFunction(object);
- else
- this.showStackFrame(null);
- },
-
- showThisSourceFile: function(sourceFile)
- {
- //-----------------------------------123456789
- if (sourceFile.href.substr(0, 9) == "chrome://")
- return false;
-
- if (sourceFile.isEval() && !this.showEvals)
- return false;
-
- if (sourceFile.isEvent() && !this.showEvents)
- return false;
-
- return true;
- },
-
- getLocationList: function()
- {
- var context = this.context;
- var allSources = sourceFilesAsArray(context);
-
- if (Firebug.showAllSourceFiles)
- {
- return allSources;
- }
-
- var filter = Firebug.getPref(Firebug.servicePrefDomain, "scriptsFilter");
- this.showEvents = (filter == "all" || filter == "events");
- this.showEvals = (filter == "all" || filter == "evals");
-
- var list = [];
- for (var i = 0; i < allSources.length; i++)
- {
- if (this.showThisSourceFile(allSources[i]))
- list.push(allSources[i]);
- }
-
- iterateWindows(context.window, function(win) {
- if (!win.document.documentElement)
- return;
- var url = win.location.href;
- if (url)
- {
- if (context.sourceFileMap.hasOwnProperty(url))
- return;
- var URLOnly = new NoScriptSourceFile(context, url);
- context.sourceFileMap[url] = URLOnly;
- list.push(URLOnly);
- }
- });
- return list;
- },
-
- getDefaultLocation: function(context)
- {
- var sourceFiles = this.getLocationList();
- if (context)
- {
- var url = context.window.location.toString();
- for (var i = 0; i < sourceFiles.length; i++)
- {
- if (url == sourceFiles[i].href)
- return sourceFiles[i];
- }
- return sourceFiles[0];
- }
- else
- return sourceFiles[0];
- },
-
- getDefaultSelection: function(context)
- {
- return this.getDefaultLocation(context);
- },
-
- getTooltipObject: function(target)
- {
- // Target should be A element with class = sourceLine
- if ( hasClass(target, 'sourceLine') )
- {
- var lineNo = parseInt(target.innerHTML);
-
- if ( isNaN(lineNo) )
- return;
- var scripts = this.location.scriptsIfLineCouldBeExecutable(lineNo);
- if (scripts)
- {
- var str = "scripts ";
- for(var i = 0; i < scripts.length; i++)
- str += scripts[i].tag +" ";
- return str;
- }
- else
- return new String("no executable script at "+lineNo);
- }
- return null;
- },
-
- getPopupObject: function(target)
- {
- // Don't show popup over the line numbers, we show the conditional breakpoint
- // editor there instead
- var sourceLine = getAncestorByClass(target, "sourceLine");
- if (sourceLine)
- return;
-
- var sourceRow = getAncestorByClass(target, "sourceRow");
- if (!sourceRow)
- return;
-
- var lineNo = parseInt(sourceRow.firstChild.textContent);
- var scripts = findScripts(this.context, this.location.href, lineNo);
- return scripts; // gee I wonder what will happen?
- },
-
- showInfoTip: function(infoTip, target, x, y, rangeParent, rangeOffset)
- {
- var frame = this.context.currentFrame;
- if (!frame)
- return;
-
- var sourceRowText = getAncestorByClass(target, "sourceRowText");
- if (!sourceRowText)
- return;
-
- // see http://code.google.com/p/fbug/issues/detail?id=889
- // idea from: Jonathan Zarate's rikaichan extension (http://www.polarcloud.com/rikaichan/)
- if (!rangeParent)
- return;
- rangeOffset = rangeOffset || 0;
- var expr = getExpressionAt(rangeParent.data, rangeOffset);
- if (!expr || !expr.expr)
- return;
-
- if (expr.expr == this.infoTipExpr)
- return true;
- else
- return this.populateInfoTip(infoTip, expr.expr);
- },
-
- getObjectPath: function(frame)
- {
- frame = this.context.debugFrame;
-
- var frames = [];
- for (; frame; frame = getCallingFrame(frame))
- frames.push(frame);
-
- return frames;
- },
-
- getObjectLocation: function(sourceFile)
- {
- return sourceFile.href;
- },
-
- // return.path: group/category label, return.name: item label
- getObjectDescription: function(sourceFile)
- {
- return sourceFile.getObjectDescription();
- },
-
- getOptionsMenuItems: function()
- {
- var context = this.context;
-
- return [
- serviceOptionMenu("BreakOnAllErrors", "breakOnErrors"),
- // wait 1.2 optionMenu("BreakOnTopLevel", "breakOnTopLevel"),
- serviceOptionMenu("ShowAllSourceFiles", "showAllSourceFiles"),
- // 1.2: always check last line; optionMenu("UseLastLineForEvalName", "useLastLineForEvalName"),
- // 1.2: always use MD5 optionMenu("UseMD5ForEvalName", "useMD5ForEvalName")
- serviceOptionMenu("TrackThrowCatch", "trackThrowCatch"),
- //"-",
- //1.2 option on toolbar this.optionMenu("DebuggerEnableAlways", enableAlwaysPref)
- ];
- },
-
- optionMenu: function(label, option)
- {
- var checked = Firebug.getPref(prefDomain, option);
- return {label: label, type: "checkbox", checked: checked,
- command: bindFixed(Firebug.setPref, Firebug, prefDomain, option, !checked) };
- },
-
- getContextMenuItems: function(fn, target)
- {
- if (getAncestorByClass(target, "sourceLine"))
- return;
-
- var sourceRow = getAncestorByClass(target, "sourceRow");
- if (!sourceRow)
- return;
-
- var sourceLine = getChildByClass(sourceRow, "sourceLine");
- var lineNo = parseInt(sourceLine.textContent);
-
- var items = [];
-
- var selection = this.document.defaultView.getSelection();
- if (selection.toString())
- {
- items.push(
- "-",
- {label: "AddWatch", command: bind(this.addSelectionWatch, this) }
- );
- }
-
- var hasBreakpoint = sourceRow.getAttribute("breakpoint") == "true";
-
- items.push(
- "-",
- {label: "SetBreakpoint", type: "checkbox", checked: hasBreakpoint,
- command: bindFixed(this.toggleBreakpoint, this, lineNo) }
- );
- if (hasBreakpoint)
- {
- var isDisabled = fbs.isBreakpointDisabled(this.location.href, lineNo);
- items.push(
- {label: "DisableBreakpoint", type: "checkbox", checked: isDisabled,
- command: bindFixed(this.toggleDisableBreakpoint, this, lineNo) }
- );
- }
- items.push(
- {label: "EditBreakpointCondition",
- command: bindFixed(this.editBreakpointCondition, this, lineNo) }
- );
-
- if (this.context.stopped)
- {
- var sourceRow = getAncestorByClass(target, "sourceRow");
- if (sourceRow)
- {
- var sourceFile = sourceRow.parentNode.repObject;
- var lineNo = parseInt(sourceRow.firstChild.textContent);
-
- var debuggr = Firebug.Debugger;
- items.push(
- "-",
- {label: "Continue",
- command: bindFixed(debuggr.resume, debuggr, this.context) },
- {label: "StepOver",
- command: bindFixed(debuggr.stepOver, debuggr, this.context) },
- {label: "StepInto",
- command: bindFixed(debuggr.stepInto, debuggr, this.context) },
- {label: "StepOut",
- command: bindFixed(debuggr.stepOut, debuggr, this.context) },
- {label: "RunUntil",
- command: bindFixed(debuggr.runUntil, debuggr, this.context,
- sourceFile, lineNo) }
- );
- }
- }
-
- return items;
- },
-
- getEditor: function(target, value)
- {
- if (!this.conditionEditor)
- this.conditionEditor = new ConditionEditor(this.document);
-
- return this.conditionEditor;
- },
-
- });
-
- // ************************************************************************************************
-
- var BreakpointsTemplate = domplate(Firebug.Rep,
- {
- tag:
- DIV({onclick: "$onClick"},
- FOR("group", "$groups",
- DIV({class: "breakpointBlock breakpointBlock-$group.name"},
- H1({class: "breakpointHeader groupHeader"},
- "$group.title"
- ),
- FOR("bp", "$group.breakpoints",
- DIV({class: "breakpointRow"},
- DIV({class: "breakpointBlockHead"},
- INPUT({class: "breakpointCheckbox", type: "checkbox",
- _checked: "$bp.checked"}),
- SPAN({class: "breakpointName"}, "$bp.name"),
- TAG(FirebugReps.SourceLink.tag, {object: "$bp|getSourceLink"}),
- IMG({class: "closeButton", src: "blank.gif"})
- ),
- DIV({class: "breakpointCode"}, "$bp.sourceLine")
- )
- )
- )
- )
- ),
-
- getSourceLink: function(bp)
- {
- return new SourceLink(bp.href, bp.lineNumber, "js");
- },
-
- onClick: function(event)
- {
- var panel = Firebug.getElementPanel(event.target);
-
- if (getAncestorByClass(event.target, "breakpointCheckbox"))
- {
- var sourceLink =
- getElementByClass(event.target.parentNode, "objectLink-sourceLink").repObject;
-
- panel.noRefresh = true;
- if (event.target.checked)
- fbs.enableBreakpoint(sourceLink.href, sourceLink.line);
- else
- fbs.disableBreakpoint(sourceLink.href, sourceLink.line);
- panel.noRefresh = false;
- }
- else if (getAncestorByClass(event.target, "closeButton"))
- {
- var sourceLink =
- getElementByClass(event.target.parentNode, "objectLink-sourceLink").repObject;
-
- panel.noRefresh = true;
-
- var head = getAncestorByClass(event.target, "breakpointBlock");
- var groupName = getClassValue(head, "breakpointBlock");
- if (groupName == "breakpoints")
- fbs.clearBreakpoint(sourceLink.href, sourceLink.line);
- else if (groupName == "errorBreakpoints")
- fbs.clearErrorBreakpoint(sourceLink.href, sourceLink.line);
- else if (groupName == "monitors")
- {
- fbs.unmonitor(sourceLink.href, sourceLink.line)
- }
-
- var row = getAncestorByClass(event.target, "breakpointRow");
- panel.removeRow(row);
-
- panel.noRefresh = false;
- }
- }
- });
-
- // ************************************************************************************************
-
- function BreakpointsPanel() {}
-
- BreakpointsPanel.prototype = extend(Firebug.Panel,
- {
- removeRow: function(row)
- {
- row.parentNode.removeChild(row);
-
- var bpCount = countBreakpoints(this.context);
- if (!bpCount)
- this.refresh();
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
-
- name: "breakpoints",
- parentPanel: "script",
- order: 2,
-
- initialize: function()
- {
- Firebug.Panel.initialize.apply(this, arguments);
- },
-
- destroy: function(state)
- {
- Firebug.Panel.destroy.apply(this, arguments);
- },
-
- show: function(state)
- {
- this.refresh();
- },
-
- refresh: function()
- {
- updateScriptFiles(this.context);
-
- var breakpoints = [];
- var errorBreakpoints = [];
- var monitors = [];
-
- var context = this.context;
-
- for (var url in this.context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url, {call: function(url, line, script, props)
- {
- if (script) // then this is a current (not future) breakpoint
- {
- var analyzer = getScriptAnalyzer(context, script);
- if (analyzer)
- var name = analyzer.getFunctionDescription(script, context).name;
- else
- var name = guessFunctionName(url, 1, context);
- var isFuture = false;
- }
- else
- {
- var isFuture = true;
- }
-
- var source = context.sourceCache.getLine(url, line);
- breakpoints.push({name : name, href: url, lineNumber: line,
- checked: !props.disabled, sourceLine: source, isFuture: isFuture});
- }});
-
- fbs.enumerateErrorBreakpoints(url, {call: function(url, line)
- {
- var name = guessEnclosingFunctionName(url, line);
- var source = context.sourceCache.getLine(url, line);
- errorBreakpoints.push({name: name, href: url, lineNumber: line, checked: true,
- sourceLine: source});
- }});
-
- fbs.enumerateMonitors(url, {call: function(url, line)
- {
- var name = guessEnclosingFunctionName(url, line);
- monitors.push({name: name, href: url, lineNumber: line, checked: true,
- sourceLine: ""});
- }});
- }
-
- function sortBreakpoints(a, b)
- {
- if (a.href == b.href)
- return a.lineNumber < b.lineNumber ? -1 : 1;
- else
- return a.href < b.href ? -1 : 1;
- }
-
- breakpoints.sort(sortBreakpoints);
- errorBreakpoints.sort(sortBreakpoints);
- monitors.sort(sortBreakpoints);
-
- var groups = [];
-
- if (breakpoints.length)
- groups.push({name: "breakpoints", title: $STR("Breakpoints"),
- breakpoints: breakpoints});
- if (errorBreakpoints.length)
- groups.push({name: "errorBreakpoints", title: $STR("ErrorBreakpoints"),
- breakpoints: errorBreakpoints});
- if (monitors.length)
- groups.push({name: "monitors", title: $STR("LoggedFunctions"),
- breakpoints: monitors});
-
- if (groups.length)
- BreakpointsTemplate.tag.replace({groups: groups}, this.panelNode);
- else
- FirebugReps.Warning.tag.replace({object: "NoBreakpointsWarning"}, this.panelNode);
-
- },
-
- getOptionsMenuItems: function()
- {
- var items = [];
-
- var context = this.context;
- updateScriptFiles(context);
-
- var bpCount = 0, disabledCount = 0;
- for (var url in context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url, {call: function(url, line, script, disabled, condition)
- {
- ++bpCount;
- if (fbs.isBreakpointDisabled(url, line))
- ++disabledCount;
- }});
- }
-
- if (disabledCount)
- {
- items.push(
- {label: "EnableAllBreakpoints",
- command: bindFixed(
- Firebug.Debugger.enableAllBreakpoints, Firebug.Debugger, context) }
- );
- }
- if (bpCount && disabledCount != bpCount)
- {
- items.push(
- {label: "DisableAllBreakpoints",
- command: bindFixed(
- Firebug.Debugger.disableAllBreakpoints, Firebug.Debugger, context) }
- );
- }
-
- items.push(
- "-",
- {label: "ClearAllBreakpoints", disabled: !bpCount,
- command: bindFixed(Firebug.Debugger.clearAllBreakpoints, Firebug.Debugger, context) }
- );
-
- return items;
- },
-
- });
-
- Firebug.DebuggerListener =
- {
- onJSDActivate: function(jsd) // start or unPause
- {
-
- },
- onJSDDeactivate: function(jsd) // stop or pause
- {
-
- },
- onStop: function(context, frame, type, rv)
- {
- },
-
- onResume: function(context)
- {
- },
-
- onThrow: function(context, frame, rv)
- {
- return false; /* continue throw */
- },
-
- onError: function(context, frame, error)
- {
- },
-
- onEventScriptCreated: function(context, frame, url)
- {
- },
-
- onTopLevelScriptCreated: function(context, frame, url)
- {
- },
-
- onEvalScriptCreated: function(context, frame, url)
- {
- },
-
- onFunctionConstructor: function(context, frame, ctor_script, url)
- {
- },
- };
-
- // ************************************************************************************************
-
- function CallstackPanel() { }
-
- CallstackPanel.prototype = extend(Firebug.Panel,
- {
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- // extends Panel
-
- name: "callstack",
- parentPanel: "script",
- order: 1,
-
- initialize: function(context, doc)
- {
- Firebug.Panel.initialize.apply(this, arguments);
- },
-
- destroy: function(state)
- {
- Firebug.Panel.destroy.apply(this, arguments);
- },
-
- show: function(state)
- {
- this.refresh();
- },
-
- supportsObject: function(object)
- {
- return object instanceof jsdIStackFrame;
- },
-
- updateSelection: function(object)
- {
- if (object instanceof jsdIStackFrame)
- this.highlightFrame(object);
- },
-
- refresh: function()
- {
- var mainPanel = this.context.getPanel("script", true);
- if (mainPanel.selection instanceof jsdIStackFrame)
- this.showStackFrame(mainPanel.selection);
- },
-
- showStackFrame: function(frame)
- {
- clearNode(this.panelNode);
- var mainPanel = this.context.getPanel("script", true);
-
- if (mainPanel && frame)
- {
- FBL.setClass(this.panelNode, "objectBox-stackTrace");
- // The panelStatus has the stack, lets reuse it to give the same UX as that control.
- var labels = panelStatus.getElementsByTagName("label");
- var doc = this.panelNode.ownerDocument;
- for (var i = 0; i < labels.length; i++)
- {
- if (FBL.hasClass(labels[i], "panelStatusLabel"))
- {
- var div = doc.createElement("div");
- var label = labels[i];
- div.innerHTML = label.getAttribute('value');
- if (label.repObject instanceof jsdIStackFrame) // causes a downcast
- div.frame = label.repObject;
- div.label = label;
- FBL.setClass(div, "objectLink");
- FBL.setClass(div, "objectLink-stackFrame");
-
- div.addEventListener("click", function(event)
- {
- var revent = document.createEvent("MouseEvents");
- revent.initMouseEvent("mousedown", true, true, window,
- 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- event.target.label.dispatchEvent(revent);
- }, false);
- this.panelNode.appendChild(div);
- }
- }
- }
- },
-
- highlightFrame: function(frame)
- {
- var frameViews = this.panelNode.childNodes
- for (var child = this.panelNode.firstChild; child; child = child.nextSibling)
- {
- if (child.label && child.label.repObject && child.label.repObject == frame)
- {
- this.selectItem(child);
- return true;
- }
- }
- return false;
- },
-
- selectItem: function(item)
- {
- if (this.selectedItem)
- this.selectedItem.removeAttribute("selected");
-
- this.selectedItem = item;
-
- if (item)
- item.setAttribute("selected", "true");
- },
-
- getOptionsMenuItems: function()
- {
- var items = [
- optionMenu("OmitObjectPathStack", "omitObjectPathStack"),
- ];
- return items;
- }
- });
-
- // ************************************************************************************************
- // Local Helpers
-
- function ConditionEditor(doc)
- {
- this.box = this.tag.replace({}, doc, this);
- this.input = this.box.childNodes[1].firstChild.firstChild.lastChild; // XXXjjb we need childNode[1] always
- this.initialize();
- }
-
- ConditionEditor.prototype = domplate(Firebug.InlineEditor.prototype,
- {
- tag:
- DIV({class: "conditionEditor"},
- DIV({class: "conditionEditorTop1"},
- DIV({class: "conditionEditorTop2"})
- ),
- DIV({class: "conditionEditorInner1"},
- DIV({class: "conditionEditorInner2"},
- DIV({class: "conditionEditorInner"},
- DIV({class: "conditionCaption"}, $STR("ConditionInput")),
- INPUT({class: "conditionInput", type: "text"})
- )
- )
- ),
- DIV({class: "conditionEditorBottom1"},
- DIV({class: "conditionEditorBottom2"})
- )
- ),
-
- show: function(sourceLine, panel, value)
- {
- this.target = sourceLine;
- this.panel = panel;
-
- this.getAutoCompleter().reset();
-
- hide(this.box, true);
- panel.selectedSourceBox.appendChild(this.box);
-
- this.input.value = value;
-
- setTimeout(bindFixed(function()
- {
- var offset = getClientOffset(sourceLine);
-
- var bottom = offset.y+sourceLine.offsetHeight;
- var y = bottom - this.box.offsetHeight;
- if (y < panel.selectedSourceBox.scrollTop)
- {
- y = offset.y;
- setClass(this.box, "upsideDown");
- }
- else
- removeClass(this.box, "upsideDown");
-
- this.box.style.top = y + "px";
- hide(this.box, false);
-
- this.input.focus();
- this.input.select();
- }, this));
- },
-
- hide: function()
- {
- this.box.parentNode.removeChild(this.box);
-
- delete this.target;
- delete this.panel;
- },
-
- layout: function()
- {
- },
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- endEditing: function(target, value, cancel)
- {
- if (!cancel)
- {
- var sourceFile = this.panel.location;
- var lineNo = parseInt(this.target.textContent);
-
- if (value)
- fbs.setBreakpointCondition(sourceFile, lineNo, value, Firebug.Debugger);
- else
- fbs.clearBreakpoint(sourceFile.href, lineNo);
- }
- }
- });
-
- // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-
- function setLineBreakpoints(sourceFile, sourceBox)
- {
- fbs.enumerateBreakpoints(sourceFile.href, {call: function(url, line, script, props)
- {
- var scriptRow = sourceBox.getLineNode(line);
- if (scriptRow)
- {
- scriptRow.setAttribute("breakpoint", "true");
- if (props.disabled)
- scriptRow.setAttribute("disabledBreakpoint", "true");
- if (props.condition)
- scriptRow.setAttribute("condition", "true");
- }
- }});
-
-
- }
-
- function getCallingFrame(frame)
- {
- try
- {
- do
- {
- frame = frame.callingFrame;
- if (!(Firebug.filterSystemURLs && isSystemURL(normalizeURL(frame.script.fileName))))
- return frame;
- }
- while (frame);
- }
- catch (exc)
- {
- }
- return null;
- }
-
-
- function getFrameScopeWindowAncestor(frame) // walk script scope chain to bottom, null unless a Window
- {
- var scope = frame.scope;
- if (scope)
- {
- while(scope.jsParent)
- scope = scope.jsParent;
-
- if (scope.jsClassName == "Window" || scope.jsClassName == "ChromeWindow")
- return scope.getWrappedValue();
-
- }
- else
- return null;
- }
-
- function getFrameWindow(frame)
- {
- var result = {};
- if (frame.eval("window", "", 1, result))
- {
- var win = result.value.getWrappedValue();
- return getRootWindow(win);
- }
- }
-
- function getFrameContext(frame)
- {
- var win = getFrameScopeWindowAncestor(frame);
- return win ? TabWatcher.getContextByWindow(win) : null;
- }
-
- function cacheAllScripts(context)
- {
- return;
- // TODO the scripts should all be ready
- for (var url in context.sourceFileMap)
- context.sourceFileMap[url].cache(context);
- }
-
- function countBreakpoints(context)
- {
- var count = 0;
- for (var url in context.sourceFileMap)
- {
- fbs.enumerateBreakpoints(url, {call: function(url, lineNo)
- {
- ++count;
- }});
- }
- return count;
- }
- /*@explore*/
- /*@explore*/
-
- // ************************************************************************************************
-
- Firebug.registerActivableModule(Firebug.Debugger);
- Firebug.registerPanel(BreakpointsPanel);
- Firebug.registerPanel(CallstackPanel);
- Firebug.registerPanel(Firebug.ScriptPanel);
-
- // ************************************************************************************************
-
- }});
-